package com.terdidik.smsserver.helper;

import java.io.StringReader;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.smslib.OutboundMessage;
import org.smslib.Message.MessageEncodings;
import org.smslib.helper.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

public class Transformer {
	
	//private static final SimpleDateFormat fileSdf = new SimpleDateFormat("yyyyMMddHHmmss-S");
	private static final SimpleDateFormat iso8601Sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");

	public Collection<OutboundMessage> xmlToOutboundMessages(String xml) {
		Collection<OutboundMessage> om = new ArrayList<OutboundMessage>();
		Document xmldoc = null;
		try {
			/* Check for valid XML file */
			DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
			// dbfac.setValidating(true);
			DocumentBuilder db = dbfac.newDocumentBuilder();
			InputSource inputSource = new InputSource();
			inputSource.setCharacterStream(new StringReader(xml));
			xmldoc = db.parse(inputSource);
			// DocumentType outDoctype = xmldoc.getDoctype();
			// if (!"message".equals(outDoctype.getName())) { throw new
			// IllegalArgumentException("Wrong DOCTYPE - Have to be message!");
			// }
			// if (!"smssvr_out.dtd".equals(outDoctype.getSystemId())) { throw
			// new
			// IllegalArgumentException("Wrong SystemId in DOCTYPE - Have to be smssvr_out.dtd!");
			// }
		} catch (Exception e) {
			throw new IllegalArgumentException(e);
		}
		/* Search "message" root element */
		NodeList n = xmldoc.getElementsByTagName("message");
		// if (rnl == null || rnl.getLength() != 1) { throw new
		// IllegalArgumentException("Wrong root element or root element count!");
		// }
		/* Process all child elements aka "message" */

		for (int x = 0; x < n.getLength(); x++) {
			Node m = n.item(x);
			if ("message".equals(m.getNodeName())) {
				String recipient = null;
				String text = null;
				String originator = null;
				String create_date = null;
				Element e = (Element) m;
				NodeList cnl = m.getChildNodes();
				/* Read required fields */
				for (int i = 0; i < cnl.getLength(); i++) {
					Node en = cnl.item(i);
					if ("recipient".equals(cnl.item(i).getNodeName())) {
						recipient = en.getTextContent();
					} else if ("text".equals(cnl.item(i).getNodeName())) {
						text = en.getTextContent();
					} else if ("originator".equals(cnl.item(i).getNodeName())) {
						originator = en.getTextContent();
					} else if ("create_date".equals(cnl.item(i).getNodeName())) {
						create_date = en.getTextContent();
					}
				}
				/* Create outbound message */
				OutboundMessage outMsg = new OutboundMessage(recipient, text);
				/* Set required fields */
				outMsg.setFrom(originator);
				if(create_date!=null) outMsg.setDate(getISO8601AsDate(create_date));
				if (!"".equals(e.getAttribute("id"))) {
					outMsg.setId(e.getAttribute("id"));
				}
				if (!"".equals(e.getAttribute("create_date"))) {
					outMsg.setDate(getISO8601AsDate(e
							.getAttribute("create_date")));
				}
				if (!"".equals(e.getAttribute("gateway_id"))) {
					outMsg.setGatewayId(e.getAttribute("gateway_id"));
				}
				/* Read optional fields - priority */
				String priority = e.getAttribute("priority");
				if ("L".equalsIgnoreCase(priority)) {
					outMsg.setPriority(-1);
				} else if ("N".equalsIgnoreCase(priority)) {
					outMsg.setPriority(0);
				} else if ("H".equalsIgnoreCase(priority)) {
					outMsg.setPriority(+1);
				}
				/* Read optional fields - encoding */
				String encoding = e.getAttribute("encoding");
				if ("7".equals(encoding)) {
					outMsg.setEncoding(MessageEncodings.ENC7BIT);
				} else if ("8".equals(encoding)) {
					outMsg.setEncoding(MessageEncodings.ENC8BIT);
				} else {
					outMsg.setEncoding(MessageEncodings.ENCUCS2);
				}
				/* Read optinal fields - status_report */
				if ("1".equals(e.getAttribute("status_report"))) {
					outMsg.setStatusReport(true);
				}
				/* Read optinal fields - flash_sms */
				if ("1".equals(e.getAttribute("flash_sms"))) {
					outMsg.setFlashSms(true);
				}
				/* Read optinal fields - src_port */
				if (!"".equals(e.getAttribute("src_port"))) {
					outMsg.setSrcPort(Integer.parseInt(e
							.getAttribute("src_port")));
				}
				/* Read optinal fields - dst_port */
				if (!"".equals(e.getAttribute("dst_port"))) {
					outMsg.setDstPort(Integer.parseInt(e
							.getAttribute("dst_port")));
				}
				om.add(outMsg);
			}
		}
		return om;
	}
	
	/**
	 * Creates a date from a ISO8601 string
	 * 
	 * @param string
	 *            The string to parse
	 * @return A date
	 */
	protected Date getISO8601AsDate(String string)
	{
		//StringBuilder sb = new StringBuilder(string);
		//sb.replace(string.length() - 3, string.length() - 2, "");
		try
		{
			return iso8601Sdf.parse(string);
		}
		catch (ParseException e)
		{
			
			Logger.getInstance().logWarn("Can't parse " + string + " as ISO8601 date!", null, null);
			return null;
		}
	}

}
